﻿using System;
using System.ServiceModel;
using System.Threading;
using CommandRunner.Contract;
using CommandRunner.Model;

namespace CommandRunner.WCFDataTransport
{
    public class CommandRunnerClient : ICommandRunnerClientDataTransport
    {
        #region ICommandRunnerClientDataTransport Members

        public bool StartCommandOnServer(CommandResult commandResult)
        {
            ChannelFactory<ICommandRunnerServer> iCommandRunnerServerFactory = null;
            ICommandRunnerServer commandRunnerServer;
            int failures = 0;

            while (true)
            {
                try
                {
                    iCommandRunnerServerFactory = new ChannelFactory<ICommandRunnerServer>(new NetTcpBinding(SecurityMode.None) { MaxReceivedMessageSize = int.MaxValue, MaxBufferSize = int.MaxValue, ReaderQuotas = new System.Xml.XmlDictionaryReaderQuotas() { MaxStringContentLength = int.MaxValue } });
                    commandRunnerServer = iCommandRunnerServerFactory.CreateChannel(new EndpointAddress(String.Format("net.tcp://{0}:{1}/CommandRunner", commandResult.Command.Server, commandResult.Command.Port)));
                    bool success = commandRunnerServer.StartCommand(commandResult);
                    iCommandRunnerServerFactory.Close();
                    return success;
                }
                catch (Exception e)
                {
                    var ecom = e as CommunicationException;
                    var tcom = e as TimeoutException;

                    if ((ecom == null) && (tcom == null))
                        throw;

                    if (++failures == 9)
                    {
                        commandResult.Output = e.GetType() + e.Message + e.StackTrace;
                        commandResult.Status = CommandExecutionStatus.Failure;
                        return false;
                    }
                    else
                        Thread.Sleep(10000);

                    iCommandRunnerServerFactory.Abort();
                }
            }

        }

        public bool CheckCommandStatusOnServer(CommandResult commandResult)
        {
            ChannelFactory<ICommandRunnerServer> iCommandRunnerServerFactory = null;
            ICommandRunnerServer commandRunnerServer;
            int failures = 0;

            while (true)
            {
                try
                {
                    iCommandRunnerServerFactory = new ChannelFactory<ICommandRunnerServer>(new NetTcpBinding(SecurityMode.None) { MaxReceivedMessageSize = int.MaxValue, MaxBufferSize = int.MaxValue, ReaderQuotas = new System.Xml.XmlDictionaryReaderQuotas() { MaxStringContentLength = int.MaxValue } });
                    commandRunnerServer = iCommandRunnerServerFactory.CreateChannel(new EndpointAddress(String.Format("net.tcp://{0}:{1}/CommandRunner", commandResult.Command.Server, commandResult.Command.Port)));
                    while (!commandRunnerServer.IsCommandFinished(commandResult.CommandId))
                    {
                        Thread.Sleep(1000);
                        failures = 0;
                    }
                    iCommandRunnerServerFactory.Close();
                    return true;
                }
                catch (Exception e)
                {
                    var ecom = e as CommunicationException;
                    var tcom = e as TimeoutException;

                    if ((ecom == null) && (tcom == null))
                        throw;

                    if (++failures == 9)
                    {
                        commandResult.Output = e.GetType() + e.Message + e.StackTrace;
                        commandResult.Status = CommandExecutionStatus.Failure;
                        return false;
                    }
                    else
                        Thread.Sleep(10000);

                    iCommandRunnerServerFactory.Abort();
                }
            }
        }

        public bool GetCommandResultFromServer(CommandResult commandResult)
        {
            ChannelFactory<ICommandRunnerServer> iCommandRunnerServerFactory = null;
            ICommandRunnerServer commandRunnerServer;
            int failures = 0;

            while (true)
            {
                try
                {
                    iCommandRunnerServerFactory = new ChannelFactory<ICommandRunnerServer>(new NetTcpBinding(SecurityMode.None) { MaxReceivedMessageSize = int.MaxValue, MaxBufferSize = int.MaxValue, ReaderQuotas = new System.Xml.XmlDictionaryReaderQuotas() { MaxStringContentLength = int.MaxValue } });
                    commandRunnerServer = iCommandRunnerServerFactory.CreateChannel(new EndpointAddress(String.Format("net.tcp://{0}:{1}/CommandRunner", commandResult.Command.Server, commandResult.Command.Port)));
                    CommandResult returnResult = commandRunnerServer.GetCommandResult(commandResult.CommandId);
                    commandResult.Output = returnResult.Output;
                    commandResult.Status = returnResult.Status;
                    iCommandRunnerServerFactory.Close();
                    return true;
                }
                catch (Exception e)
                {
                    var ecom = e as CommunicationException;
                    var tcom = e as TimeoutException;

                    if ((ecom == null) && (tcom == null))
                        throw;

                    if (++failures == 9)
                    {
                        commandResult.Output = e.GetType() + e.Message + e.StackTrace;
                        commandResult.Status = CommandExecutionStatus.Failure;
                        return false;
                    }
                    else
                        Thread.Sleep(10000);

                    iCommandRunnerServerFactory.Abort();
                }
            }
        }

        #endregion
    }
}
